package lambda;


import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @author 江岸
 * @version V1.0
 * @ClassName: Test1
 * @description: lambda使用例子
 * @date 2020/9/2115:32
 * @since V1.0
 */
public class Test1 {
    public static void main(String[] args) {
        fun2();
    }
    /*
     *lambda写法
     */
    public static void fun1(){
        List<String> list = Arrays.asList("a", "b", "c");
        //完整的lambda表达式
        list.forEach(n -> System.out.print(n));
        System.out.println();
        System.out.println("-------------------------");
        //使用方法引用.在不改参数的情况下
        list.forEach(System.out::print);
        System.out.println();
        System.out.println("-------------------------");
        //若需要修改参数，则写完整的表达式
        list.forEach(n -> System.out.print(n+","));
        //特殊性，无法在lambda表达式内对外部变量进行修改，只能访问。
    }
    /*
     * filter
     * filter 方法用于通过设置的条件过滤出元素。
     */
    public static void fun2(){
        List<String> list = Arrays.asList("a", "b", "c");
        //惰性求值方法
        Stream<String> stream = list.stream().filter(f -> !f.equals("b"));
        //System.out.println(stream.count());
        //stream对象只能使用一次，上面这里打印了，下面的方法就会报错。
        //及早求值方法，collect最终会从Stream产生新值，拥有终止操作。
        List<String> collect = stream.collect(Collectors.toList());
        System.out.println(collect);
    }
    
    /*
     * stream & parallelStream
     *
     * 每个Stream都有两种模式: 顺序执行和并行执行。
     */
    public static void fun3(){
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
        //顺序流.当使用顺序方式去遍历时，每个item读完后再读下一个item。
        list.stream().forEach(n -> System.out.print(n+","));
        System.out.println();
        //并行流。使用并行去遍历时，数组会被分成多个段，其中每一个都在不同的线程中处理，然后将结果一起输出。
        list.parallelStream().forEach(n -> System.out.print(n+","));
    }

    /*
     *如果是多核机器，理论上并行流则会比顺序流快上一倍
     */
    public static void fun4(){
        long t0 = System.nanoTime();
        //初始化一个范围100万整数流,求能被2整除的数字，toArray()是终点方法
        int[] a = IntStream.range(0, 1_000_000).filter(p -> p % 2 == 0).toArray();
        long t1 = System.nanoTime();
        //和上面功能一样，这里是用并行流来计算
        int[] b = IntStream.range(0, 1_000_000).parallel().filter(p -> p % 2 == 0).toArray();
        long t2 = System.nanoTime();
        System.out.printf("serial: %.2fs, parallel %.2fs%n", (t1 - t0) * 1e-9, (t2 - t1) * 1e-9);
        //打印结果 serial: 0.12s, parallel 0.03s
    }


}
